Preparations

knitr::opts_knit$set(root.dir = rprojroot::find_rstudio_root_file(), 
                     fig.width=14,
                     fig.height=14)
options(readr.show_progress = FALSE,
        digits=5, 
        scipen=8)
set.seed(42)
library(tidyverse)

Read data

tx_gene_meta <- read_csv("./data/hg_ens97_metadata.txt")
tx_gene_meta

Gene Level

Extract Gene metadata

gene_meta <- 
  tx_gene_meta %>%
         dplyr::group_by(gene_id_version) %>%
         dplyr::slice(1) %>%
  ungroup() %>%
  select(gene_name, gene_len, perc_gene_gc, gene_id, seqnames, gene_biotype, gene_id_version)
gene_meta

Some gene names are not unique

duplicated_gene_names <-
  gene_meta %>%
  dplyr::filter( duplicated(gene_name))%>%
  pull(gene_name)%>%
  unique()
  

length(duplicated_gene_names)
[1] 147
gene_meta %>%
  dplyr::filter(gene_name%in% duplicated_gene_names ) %>%
  arrange(gene_name)

Gene Biotypes

biotype_count <-
  gene_meta %>% 
  group_by(gene_biotype) %>% 
  tally(sort = TRUE)
biotype_count
biotype_targets <-
  biotype_count %>%
  slice(1:10)%>% 
  pull(gene_biotype)

Percentage of Gene GC Content

ggplot(gene_meta %>%
         filter(gene_biotype %in% biotype_targets),
       aes(perc_gene_gc)) +
  geom_histogram(bins = 150)   +
  facet_wrap(~gene_biotype)

ggplot(gene_meta %>%
         filter(gene_biotype %in% biotype_targets) ,
       aes(gene_len)) +
  geom_histogram(bins = 150)  +  
   scale_x_log10() +
  facet_wrap(~gene_biotype)

ggplot(gene_meta %>%
         filter(gene_biotype %in% biotype_targets), 
       aes(perc_gene_gc, gene_len))+
  geom_point(size=0.8,
              alpha=0.7) +
  geom_density_2d() +  
   scale_y_log10() +
   theme(legend.position="none") +
  facet_wrap(~gene_biotype)

Transcript Level

Transcript Biotypes

tx_biotype_count <-
  tx_gene_meta %>% 
  group_by(tx_biotype) %>% 
  tally(sort = TRUE)
tx_biotype_count
tx_biotype_targets <-
  tx_biotype_count %>%
  slice(1:8)%>% 
  pull(tx_biotype)

Exonic vs intronic lengths

ggplot(tx_gene_meta %>%
         filter(tx_biotype %in% tx_biotype_targets)) +
  geom_point( aes(exonic_len, intronic_len, colour=perc_gene_gc),
              size=0.3,
              alpha=0.6)  +  
  scale_x_log10() +
   scale_y_log10() +
  facet_wrap(~tx_biotype) +
  scale_colour_gradient2(midpoint=10, mid = "yellow")

Exonic vs intronic counts

ggplot(tx_gene_meta %>%
         filter(tx_biotype %in% tx_biotype_targets)) +
  geom_point( aes(nexon, nintron, colour=gene_len),
              size=0.8,
              alpha=0.7)  +  
  scale_x_log10() +
   scale_y_log10()  +
  facet_wrap(~tx_biotype) 

Pre-mRNA vs Exonic lengths

ggplot(tx_gene_meta %>%
         filter(tx_biotype %in% tx_biotype_targets & nexon!=1),
       aes( premrna_len, exonic_len, colour=nexon)) +
  geom_point( size=0.1,
              alpha=0.3)  +    
  geom_density_2d() +  
  scale_x_log10() +
   scale_y_log10() +
  facet_wrap(~tx_biotype) 

Exonic Counts vs Exonic lengths

ggplot(tx_gene_meta %>%
         filter(tx_biotype %in% tx_biotype_targets ),
       aes( nexon, exonic_len, colour=premrna_len)) +
  geom_point( size=0.1,
              alpha=0.3)  +    
  scale_x_log10() +
   scale_y_log10() +
  facet_wrap(~tx_biotype) 

Number of transcipts by gene

count_tx_by_gene <-
  tx_gene_meta %>%
  count(gene_id,gene_name, gene_biotype) %>%
  arrange(-n)
count_tx_by_gene 
ggplot(count_tx_by_gene, aes(n)) +
  geom_histogram(bins = 100)  

top_genes <- 
  count_tx_by_gene %>%
  slice(1:20) %>%
  pull(gene_name)
top_genes
 [1] "PCBP1-AS1" "MAPK10"    "TEX41"     "PVT1"      "LINC00635" "MIR663AHG" "MIR99AHG"  "SNHG14"    "MUC20-OT1" "LINC00343" "LINC00293" "HULC"      "LINC00511"
[14] "CASC15"    "SOX2-OT"   "LINC01206" "SGCE"      "SPG7"      "KCNMA1"    "TCF4"     
ggplot(tx_gene_meta %>% 
         dplyr::filter(gene_name%in% top_genes))+
  geom_point( aes(exonic_len, intronic_len, colour=nexon >=10)) +
  facet_wrap(gene_biotype~gene_name,   scales = "free")

tx_10_genes <- 
  count_tx_by_gene %>%
  filter(n==10) %>%
  slice(1:20) %>%
  pull(gene_name)
ggplot(tx_gene_meta %>% 
         dplyr::filter(gene_name%in% tx_10_genes))+
  geom_point( aes(exonic_len, intronic_len, colour=nexon >=10)) +
  facet_wrap(~gene_name,  scales = "free") 

NA
single_transcript_genes <-
  count_tx_by_gene %>% 
  dplyr::filter(n==1) %>% 
  pull(gene_name)
length(single_transcript_genes)
[1] 37383
ggplot(tx_gene_meta  %>% 
         dplyr::filter(gene_name%in% single_transcript_genes & gene_biotype %in% biotype_targets ))+
  geom_point( aes(exonic_len, intronic_len,  colour=perc_gene_gc),
              size=0.2,
              alpha=0.5)  +  
  scale_x_log10() +
   scale_y_log10() +
  facet_wrap(~tx_biotype)  +
  scale_colour_gradient2(midpoint=10, mid = "yellow")

Single exon transcripts

  tx_gene_meta %>%
  count(nexon ) %>%
  arrange(-n)
ggplot(tx_gene_meta %>% 
         dplyr::filter(tx_biotype %in% tx_biotype_targets & nexon== 2)) +
  geom_point( aes(exonic_len, intronic_len,  colour=perc_gene_gc),
              size=0.2,
              alpha=0.5)  +  
  scale_x_log10() +
   scale_y_log10() +
  facet_wrap(~tx_biotype)  +
  scale_colour_gradient2(midpoint=10, mid = "yellow")

ggplot(tx_gene_meta %>% 
         dplyr::filter(tx_biotype %in% tx_biotype_targets & nexon< 10 & nexon> 1)) +
  geom_point( aes(exonic_len, intronic_len,  colour=perc_gene_gc),
              size=0.2,
              alpha=0.5)  +  
  scale_x_log10() +
   scale_y_log10() +
  facet_wrap(~tx_biotype)  +
  scale_colour_gradient2(midpoint=10, mid = "yellow")

ggplot(tx_gene_meta %>% 
         dplyr::filter(tx_biotype %in% tx_biotype_targets & nexon>= 10)) +
  geom_point( aes(exonic_len, intronic_len,  colour=perc_gene_gc),
              size=0.2,
              alpha=0.5)  +  
  scale_x_log10() +
   scale_y_log10() +
  facet_wrap(~tx_biotype)  +
  scale_colour_gradient2(midpoint=10, mid = "yellow")

sessionInfo()
R version 3.6.1 (2019-07-05)
Platform: x86_64-pc-linux-gnu (64-bit)
Running under: Ubuntu 18.04.3 LTS

Matrix products: default
BLAS:   /usr/lib/x86_64-linux-gnu/blas/libblas.so.3.7.1
LAPACK: /usr/lib/x86_64-linux-gnu/lapack/liblapack.so.3.7.1

locale:
 [1] LC_CTYPE=en_US.UTF-8       LC_NUMERIC=C               LC_TIME=en_US.UTF-8        LC_COLLATE=en_US.UTF-8     LC_MONETARY=en_US.UTF-8    LC_MESSAGES=en_US.UTF-8   
 [7] LC_PAPER=en_US.UTF-8       LC_NAME=C                  LC_ADDRESS=C               LC_TELEPHONE=C             LC_MEASUREMENT=en_US.UTF-8 LC_IDENTIFICATION=C       

attached base packages:
[1] stats     graphics  grDevices utils     datasets  methods   base     

other attached packages:
[1] forcats_0.4.0   stringr_1.4.0   dplyr_0.8.3     purrr_0.3.2     readr_1.3.1     tidyr_0.8.3     tibble_2.1.3    ggplot2_3.2.1   tidyverse_1.2.1

loaded via a namespace (and not attached):
 [1] Rcpp_1.0.2       cellranger_1.1.0 pillar_1.4.2     compiler_3.6.1   tools_3.6.1      digest_0.6.20    zeallot_0.1.0    lubridate_1.7.4  jsonlite_1.6    
[10] nlme_3.1-140     gtable_0.3.0     lattice_0.20-38  pkgconfig_2.0.2  rlang_0.4.0      cli_1.1.0        rstudioapi_0.10  haven_2.1.1      xfun_0.8        
[19] withr_2.1.2      xml2_1.2.2       httr_1.4.1       knitr_1.24       generics_0.0.2   vctrs_0.2.0      hms_0.5.0        rprojroot_1.3-2  grid_3.6.1      
[28] tidyselect_0.2.5 glue_1.3.1       R6_2.4.0         readxl_1.3.1     modelr_0.1.5     magrittr_1.5     MASS_7.3-51.4    backports_1.1.4  scales_1.0.0    
[37] rvest_0.3.4      assertthat_0.2.1 colorspace_1.4-1 labeling_0.3     stringi_1.4.3    lazyeval_0.2.2   munsell_0.5.0    broom_0.5.2      crayon_1.3.4    
LS0tCnRpdGxlOiAiRXhwbG9yZSBodW1hbiBtZXRhZGF0YSIKYXV0aG9yOiAKLSBuYW1lOiBSaWNrIEZhcm91bmkKICBhZmZpbGlhdGlvbjoKICAtICZjcnVrIERlcGFydG1lbnQgb2YgSHVtYW4gR2VuZXRpY3MsIE1jR2lsbCBVbml2ZXJzaXR5LCAgTW9udHJlYWwsIENhbmFkYQpkYXRlOiAnYHIgZm9ybWF0KFN5cy5EYXRlKCksICIlWS0lQi0lZCIpYCcKb3V0cHV0OiBodG1sX25vdGVib29rCi0tLQoKCiMgUHJlcGFyYXRpb25zCgpgYGB7ciBzZXR1cH0Ka25pdHI6Om9wdHNfa25pdCRzZXQocm9vdC5kaXIgPSBycHJvanJvb3Q6OmZpbmRfcnN0dWRpb19yb290X2ZpbGUoKSwgCiAgICAgICAgICAgICAgICAgICAgIGZpZy53aWR0aD0xNCwKICAgICAgICAgICAgICAgICAgICAgZmlnLmhlaWdodD0xNCkKb3B0aW9ucyhyZWFkci5zaG93X3Byb2dyZXNzID0gRkFMU0UsCiAgICAgICAgZGlnaXRzPTUsIAogICAgICAgIHNjaXBlbj04KQpzZXQuc2VlZCg0MikKYGBgCgoKYGBge3IgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRX0KbGlicmFyeSh0aWR5dmVyc2UpCmBgYAoKCiMjIFJlYWQgZGF0YQoKCgpgYGB7ciBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQp0eF9nZW5lX21ldGEgPC0gcmVhZF9jc3YoIi4vZGF0YS9oZ19lbnM5N19tZXRhZGF0YS50eHQiKQp0eF9nZW5lX21ldGEKYGBgCgojIEdlbmUgTGV2ZWwgCgojIyBFeHRyYWN0IEdlbmUgbWV0YWRhdGEKCmBgYHtyfQpnZW5lX21ldGEgPC0gCiAgdHhfZ2VuZV9tZXRhICU+JQogICAgICAgICBkcGx5cjo6Z3JvdXBfYnkoZ2VuZV9pZF92ZXJzaW9uKSAlPiUKICAgICAgICAgZHBseXI6OnNsaWNlKDEpICU+JQogIHVuZ3JvdXAoKSAlPiUKICBzZWxlY3QoZ2VuZV9uYW1lLCBnZW5lX2xlbiwgcGVyY19nZW5lX2djLCBnZW5lX2lkLCBzZXFuYW1lcywgZ2VuZV9iaW90eXBlLCBnZW5lX2lkX3ZlcnNpb24pCmdlbmVfbWV0YQpgYGAKCgpTb21lIGdlbmUgbmFtZXMgYXJlIG5vdCB1bmlxdWUKCmBgYHtyfQpkdXBsaWNhdGVkX2dlbmVfbmFtZXMgPC0KICBnZW5lX21ldGEgJT4lCiAgZHBseXI6OmZpbHRlciggZHVwbGljYXRlZChnZW5lX25hbWUpKSU+JQogIHB1bGwoZ2VuZV9uYW1lKSU+JQogIHVuaXF1ZSgpCiAgCgpsZW5ndGgoZHVwbGljYXRlZF9nZW5lX25hbWVzKQpgYGAKCmBgYHtyfQpnZW5lX21ldGEgJT4lCiAgZHBseXI6OmZpbHRlcihnZW5lX25hbWUlaW4lIGR1cGxpY2F0ZWRfZ2VuZV9uYW1lcyApICU+JQogIGFycmFuZ2UoZ2VuZV9uYW1lKQpgYGAKCgojIyMgR2VuZSBCaW90eXBlcwoKCmBgYHtyfQpiaW90eXBlX2NvdW50IDwtCiAgZ2VuZV9tZXRhICU+JSAKICBncm91cF9ieShnZW5lX2Jpb3R5cGUpICU+JSAKICB0YWxseShzb3J0ID0gVFJVRSkKYmlvdHlwZV9jb3VudApgYGAKCmBgYHtyfQpiaW90eXBlX3RhcmdldHMgPC0KICBiaW90eXBlX2NvdW50ICU+JQogIHNsaWNlKDE6MTApJT4lIAogIHB1bGwoZ2VuZV9iaW90eXBlKQpgYGAKCgoKIyMjIFBlcmNlbnRhZ2Ugb2YgR2VuZSBHQyBDb250ZW50CgoKYGBge3IgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRSwgZmlnLmhlaWdodD0xMCwgZmlnLndpZHRoPTEyfQpnZ3Bsb3QoZ2VuZV9tZXRhICU+JQogICAgICAgICBmaWx0ZXIoZ2VuZV9iaW90eXBlICVpbiUgYmlvdHlwZV90YXJnZXRzKSwKICAgICAgIGFlcyhwZXJjX2dlbmVfZ2MpKSArCiAgZ2VvbV9oaXN0b2dyYW0oYmlucyA9IDE1MCkgICArCiAgZmFjZXRfd3JhcCh+Z2VuZV9iaW90eXBlKQpgYGAKCgpgYGB7ciBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFLCBmaWcuaGVpZ2h0PTEwLCBmaWcud2lkdGg9MTJ9CmdncGxvdChnZW5lX21ldGEgJT4lCiAgICAgICAgIGZpbHRlcihnZW5lX2Jpb3R5cGUgJWluJSBiaW90eXBlX3RhcmdldHMpICwKICAgICAgIGFlcyhnZW5lX2xlbikpICsKICBnZW9tX2hpc3RvZ3JhbShiaW5zID0gMTUwKSAgKyAgCiAgIHNjYWxlX3hfbG9nMTAoKSArCiAgZmFjZXRfd3JhcCh+Z2VuZV9iaW90eXBlKQpgYGAKCmBgYHtyLCBmaWcud2lkdGg9MjB9CmdncGxvdChnZW5lX21ldGEgJT4lCiAgICAgICAgIGZpbHRlcihnZW5lX2Jpb3R5cGUgJWluJSBiaW90eXBlX3RhcmdldHMpLCAKICAgICAgIGFlcyhwZXJjX2dlbmVfZ2MsIGdlbmVfbGVuKSkrCiAgZ2VvbV9wb2ludChzaXplPTAuOCwKICAgICAgICAgICAgICBhbHBoYT0wLjcpICsKICBnZW9tX2RlbnNpdHlfMmQoKSArICAKICAgc2NhbGVfeV9sb2cxMCgpICsKICAgdGhlbWUobGVnZW5kLnBvc2l0aW9uPSJub25lIikgKwogIGZhY2V0X3dyYXAofmdlbmVfYmlvdHlwZSkKYGBgCgoKCiMgVHJhbnNjcmlwdCBMZXZlbCAKCiMjIyBUcmFuc2NyaXB0IEJpb3R5cGVzCgoKYGBge3J9CnR4X2Jpb3R5cGVfY291bnQgPC0KICB0eF9nZW5lX21ldGEgJT4lIAogIGdyb3VwX2J5KHR4X2Jpb3R5cGUpICU+JSAKICB0YWxseShzb3J0ID0gVFJVRSkKdHhfYmlvdHlwZV9jb3VudApgYGAKCmBgYHtyfQp0eF9iaW90eXBlX3RhcmdldHMgPC0KICB0eF9iaW90eXBlX2NvdW50ICU+JQogIHNsaWNlKDE6OCklPiUgCiAgcHVsbCh0eF9iaW90eXBlKQpgYGAKCiMjIEV4b25pYyB2cyBpbnRyb25pYyBsZW5ndGhzCgpgYGB7ciwgZmlnLndpZHRoPTE2fQpnZ3Bsb3QodHhfZ2VuZV9tZXRhICU+JQogICAgICAgICBmaWx0ZXIodHhfYmlvdHlwZSAlaW4lIHR4X2Jpb3R5cGVfdGFyZ2V0cykpICsKICBnZW9tX3BvaW50KCBhZXMoZXhvbmljX2xlbiwgaW50cm9uaWNfbGVuLCBjb2xvdXI9cGVyY19nZW5lX2djKSwKICAgICAgICAgICAgICBzaXplPTAuMywKICAgICAgICAgICAgICBhbHBoYT0wLjYpICArICAKICBzY2FsZV94X2xvZzEwKCkgKwogICBzY2FsZV95X2xvZzEwKCkgKwogIGZhY2V0X3dyYXAofnR4X2Jpb3R5cGUpICsKICBzY2FsZV9jb2xvdXJfZ3JhZGllbnQyKG1pZHBvaW50PTEwLCBtaWQgPSAieWVsbG93IikKCmBgYAoKCgoKCgoKCiMjIEV4b25pYyB2cyBpbnRyb25pYyBjb3VudHMKCgpgYGB7ciwgZmlnLndpZHRoPTIwfQpnZ3Bsb3QodHhfZ2VuZV9tZXRhICU+JQogICAgICAgICBmaWx0ZXIodHhfYmlvdHlwZSAlaW4lIHR4X2Jpb3R5cGVfdGFyZ2V0cykpICsKICBnZW9tX3BvaW50KCBhZXMobmV4b24sIG5pbnRyb24sIGNvbG91cj1nZW5lX2xlbiksCiAgICAgICAgICAgICAgc2l6ZT0wLjgsCiAgICAgICAgICAgICAgYWxwaGE9MC43KSAgKyAgCiAgc2NhbGVfeF9sb2cxMCgpICsKICAgc2NhbGVfeV9sb2cxMCgpICArCiAgZmFjZXRfd3JhcCh+dHhfYmlvdHlwZSkgCmBgYAoKCiMjIFByZS1tUk5BIHZzIEV4b25pYyBsZW5ndGhzCgoKYGBge3IsIGZpZy53aWR0aD0yMH0KZ2dwbG90KHR4X2dlbmVfbWV0YSAlPiUKICAgICAgICAgZmlsdGVyKHR4X2Jpb3R5cGUgJWluJSB0eF9iaW90eXBlX3RhcmdldHMgJiBuZXhvbiE9MSksCiAgICAgICBhZXMoIHByZW1ybmFfbGVuLCBleG9uaWNfbGVuLCBjb2xvdXI9bmV4b24pKSArCiAgZ2VvbV9wb2ludCggc2l6ZT0wLjEsCiAgICAgICAgICAgICAgYWxwaGE9MC4zKSAgKyAgICAKICBnZW9tX2RlbnNpdHlfMmQoKSArICAKICBzY2FsZV94X2xvZzEwKCkgKwogICBzY2FsZV95X2xvZzEwKCkgKwogIGZhY2V0X3dyYXAofnR4X2Jpb3R5cGUpIApgYGAKCiMjIEV4b25pYyBDb3VudHMgdnMgRXhvbmljIGxlbmd0aHMKCgpgYGB7ciwgZmlnLndpZHRoPTIwfQpnZ3Bsb3QodHhfZ2VuZV9tZXRhICU+JQogICAgICAgICBmaWx0ZXIodHhfYmlvdHlwZSAlaW4lIHR4X2Jpb3R5cGVfdGFyZ2V0cyApLAogICAgICAgYWVzKCBuZXhvbiwgZXhvbmljX2xlbiwgY29sb3VyPXByZW1ybmFfbGVuKSkgKwogIGdlb21fcG9pbnQoIHNpemU9MC4xLAogICAgICAgICAgICAgIGFscGhhPTAuMykgICsgICAgCiAgc2NhbGVfeF9sb2cxMCgpICsKICAgc2NhbGVfeV9sb2cxMCgpICsKICBmYWNldF93cmFwKH50eF9iaW90eXBlKSAKYGBgCiMjIE51bWJlciBvZiB0cmFuc2NpcHRzIGJ5IGdlbmUKCmBgYHtyfQpjb3VudF90eF9ieV9nZW5lIDwtCiAgdHhfZ2VuZV9tZXRhICU+JQogIGNvdW50KGdlbmVfaWQsZ2VuZV9uYW1lLCBnZW5lX2Jpb3R5cGUpICU+JQogIGFycmFuZ2UoLW4pCmNvdW50X3R4X2J5X2dlbmUgCmBgYAoKCmBgYHtyIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0UsIGZpZy5oZWlnaHQ9NCwgZmlnLndpZHRoPTd9CmdncGxvdChjb3VudF90eF9ieV9nZW5lLCBhZXMobikpICsKICBnZW9tX2hpc3RvZ3JhbShiaW5zID0gMTAwKSAgCmBgYApgYGB7cn0KdG9wX2dlbmVzIDwtIAogIGNvdW50X3R4X2J5X2dlbmUgJT4lCiAgc2xpY2UoMToyMCkgJT4lCiAgcHVsbChnZW5lX25hbWUpCnRvcF9nZW5lcwpgYGAKCgpgYGB7ciBmaWcuaGVpZ2h0PTE1fQpnZ3Bsb3QodHhfZ2VuZV9tZXRhICU+JSAKICAgICAgICAgZHBseXI6OmZpbHRlcihnZW5lX25hbWUlaW4lIHRvcF9nZW5lcykpKwogIGdlb21fcG9pbnQoIGFlcyhleG9uaWNfbGVuLCBpbnRyb25pY19sZW4sIGNvbG91cj1uZXhvbiA+PTEwKSkgKwogIGZhY2V0X3dyYXAoZ2VuZV9iaW90eXBlfmdlbmVfbmFtZSwgICBzY2FsZXMgPSAiZnJlZSIpCmBgYAoKCgoKYGBge3J9CnR4XzEwX2dlbmVzIDwtIAogIGNvdW50X3R4X2J5X2dlbmUgJT4lCiAgZmlsdGVyKG49PTEwKSAlPiUKICBzbGljZSgxOjIwKSAlPiUKICBwdWxsKGdlbmVfbmFtZSkKYGBgCgoKCmBgYHtyIGZpZy5oZWlnaHQ9MTV9CmdncGxvdCh0eF9nZW5lX21ldGEgJT4lIAogICAgICAgICBkcGx5cjo6ZmlsdGVyKGdlbmVfbmFtZSVpbiUgdHhfMTBfZ2VuZXMpKSsKICBnZW9tX3BvaW50KCBhZXMoZXhvbmljX2xlbiwgaW50cm9uaWNfbGVuLCBjb2xvdXI9bmV4b24gPj0xMCkpICsKICBmYWNldF93cmFwKH5nZW5lX25hbWUsICBzY2FsZXMgPSAiZnJlZSIpIAogIApgYGAKCgpgYGB7cn0Kc2luZ2xlX3RyYW5zY3JpcHRfZ2VuZXMgPC0KICBjb3VudF90eF9ieV9nZW5lICU+JSAKICBkcGx5cjo6ZmlsdGVyKG49PTEpICU+JSAKICBwdWxsKGdlbmVfbmFtZSkKbGVuZ3RoKHNpbmdsZV90cmFuc2NyaXB0X2dlbmVzKQpgYGAKCgoKYGBge3IgZmlnLmhlaWdodD04fQpnZ3Bsb3QodHhfZ2VuZV9tZXRhICAlPiUgCiAgICAgICAgIGRwbHlyOjpmaWx0ZXIoZ2VuZV9uYW1lJWluJSBzaW5nbGVfdHJhbnNjcmlwdF9nZW5lcyAmIGdlbmVfYmlvdHlwZSAlaW4lIGJpb3R5cGVfdGFyZ2V0cyApKSsKICBnZW9tX3BvaW50KCBhZXMoZXhvbmljX2xlbiwgaW50cm9uaWNfbGVuLCAgY29sb3VyPXBlcmNfZ2VuZV9nYyksCiAgICAgICAgICAgICAgc2l6ZT0wLjIsCiAgICAgICAgICAgICAgYWxwaGE9MC41KSAgKyAgCiAgc2NhbGVfeF9sb2cxMCgpICsKICAgc2NhbGVfeV9sb2cxMCgpICsKICBmYWNldF93cmFwKH50eF9iaW90eXBlKSAgKwogIHNjYWxlX2NvbG91cl9ncmFkaWVudDIobWlkcG9pbnQ9MTAsIG1pZCA9ICJ5ZWxsb3ciKQoKYGBgCgojIFNpbmdsZSBleG9uIHRyYW5zY3JpcHRzCgoKYGBge3J9CiAgdHhfZ2VuZV9tZXRhICU+JQogIGNvdW50KG5leG9uICkgJT4lCiAgYXJyYW5nZSgtbikKYGBgCgoKCgpgYGB7ciBmaWcuaGVpZ2h0PTEwfQpnZ3Bsb3QodHhfZ2VuZV9tZXRhICU+JSAKICAgICAgICAgZHBseXI6OmZpbHRlcih0eF9iaW90eXBlICVpbiUgdHhfYmlvdHlwZV90YXJnZXRzICYgbmV4b249PSAyKSkgKwogIGdlb21fcG9pbnQoIGFlcyhleG9uaWNfbGVuLCBpbnRyb25pY19sZW4sICBjb2xvdXI9cGVyY19nZW5lX2djKSwKICAgICAgICAgICAgICBzaXplPTAuMiwKICAgICAgICAgICAgICBhbHBoYT0wLjUpICArICAKICBzY2FsZV94X2xvZzEwKCkgKwogICBzY2FsZV95X2xvZzEwKCkgKwogIGZhY2V0X3dyYXAofnR4X2Jpb3R5cGUpICArCiAgc2NhbGVfY29sb3VyX2dyYWRpZW50MihtaWRwb2ludD0xMCwgbWlkID0gInllbGxvdyIpCmBgYAoKCmBgYHtyIGZpZy5oZWlnaHQ9MTB9CmdncGxvdCh0eF9nZW5lX21ldGEgJT4lIAogICAgICAgICBkcGx5cjo6ZmlsdGVyKHR4X2Jpb3R5cGUgJWluJSB0eF9iaW90eXBlX3RhcmdldHMgJiBuZXhvbjwgMTAgJiBuZXhvbj4gMSkpICsKICBnZW9tX3BvaW50KCBhZXMoZXhvbmljX2xlbiwgaW50cm9uaWNfbGVuLCAgY29sb3VyPXBlcmNfZ2VuZV9nYyksCiAgICAgICAgICAgICAgc2l6ZT0wLjIsCiAgICAgICAgICAgICAgYWxwaGE9MC41KSAgKyAgCiAgc2NhbGVfeF9sb2cxMCgpICsKICAgc2NhbGVfeV9sb2cxMCgpICsKICBmYWNldF93cmFwKH50eF9iaW90eXBlKSAgKwogIHNjYWxlX2NvbG91cl9ncmFkaWVudDIobWlkcG9pbnQ9MTAsIG1pZCA9ICJ5ZWxsb3ciKQpgYGAKCmBgYHtyIGZpZy5oZWlnaHQ9MTB9CmdncGxvdCh0eF9nZW5lX21ldGEgJT4lIAogICAgICAgICBkcGx5cjo6ZmlsdGVyKHR4X2Jpb3R5cGUgJWluJSB0eF9iaW90eXBlX3RhcmdldHMgJiBuZXhvbj49IDEwKSkgKwogIGdlb21fcG9pbnQoIGFlcyhleG9uaWNfbGVuLCBpbnRyb25pY19sZW4sICBjb2xvdXI9cGVyY19nZW5lX2djKSwKICAgICAgICAgICAgICBzaXplPTAuMiwKICAgICAgICAgICAgICBhbHBoYT0wLjUpICArICAKICBzY2FsZV94X2xvZzEwKCkgKwogICBzY2FsZV95X2xvZzEwKCkgKwogIGZhY2V0X3dyYXAofnR4X2Jpb3R5cGUpICArCiAgc2NhbGVfY29sb3VyX2dyYWRpZW50MihtaWRwb2ludD0xMCwgbWlkID0gInllbGxvdyIpCmBgYAoKCgoKYGBge3J9CnNlc3Npb25JbmZvKCkKYGBg